package org.hk.proxy.server.web;

import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpRequest;
import lombok.Data;
import org.hk.proxy.common.exception.ApiCommonException;
import org.hk.proxy.server.web.handler.LoginHandler;
import org.hk.proxy.server.web.handler.MenuListHandler;
import org.hk.proxy.server.web.handler.RegisterHandler;
import org.hk.proxy.server.web.handler.RequestHandler;
import org.hk.proxy.server.web.interceptor.HttpInterceptor;
import org.hk.proxy.server.web.interceptor.LoginInterceptor;
import org.hk.proxy.server.web.interceptor.UriHttpInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ApiRouteResolve {
    private static Logger logger = LoggerFactory.getLogger(ApiRouteResolve.class);
    private static final Map<String, ApiRoute> API_ROUTE_MAP = new HashMap<>();

    private static final List<HttpInterceptor> GlobPreRequestMiddleware = new ArrayList<>();
    public static ApiRouteResolve apiRouteResolve = new ApiRouteResolve();
    public static void addRoute(ApiRoute route) {
        logger.info("add route ,path:{}", route.path);
        API_ROUTE_MAP.put(route.getPath(), route);
    }
    public static ApiRoute getRoute(String path) {
        return API_ROUTE_MAP.get(path);
    }

    public static ApiRouteBuilder builder() {
        return new ApiRouteBuilder();
    }

    public static void writeAndFlush(ChannelHandlerContext context, HttpRequest request) {
        try {
            /**
             * 先拦截器执行
             */
            for (HttpInterceptor requestMiddleware : GlobPreRequestMiddleware) {
                requestMiddleware.preRequest(request);
            }
            new ResponseWrapper(context, getRoute(request.uri())).writeAndFlush(request);
        } catch (ApiCommonException e) {
            ResponseWrapper.outputContent(context, request, Result.of(e.getCode(), e.getMessage()));
        }

    }

    public static boolean containRoute(String uri) {
        return API_ROUTE_MAP.containsKey(uri);
    }


    public ApiRouteResolve() {
        //get请求参数url转换
        GlobPreRequestMiddleware.add(new UriHttpInterceptor());
        /**
         * 登录拦截
         */
        GlobPreRequestMiddleware.add(new LoginInterceptor());
        /**
         * 登录
         */
        addRoute(builder().path("/login").method("post").requestHandler(new LoginHandler()).build());
        /**
         * 注册
         */
        addRoute(builder().path("/register").method("post").requestHandler(new RegisterHandler()).build());
        addRoute(builder().path("/menus").method("get").requestHandler(new MenuListHandler()).build());
    }

    public static class ApiRouteBuilder {
        private String path;
        private RequestHandler requestHandler;
        private HttpInterceptor requestMiddleware;
        private String method;

        public ApiRouteBuilder path(String path) {
            this.path = path;
            return this;
        }

        public ApiRouteBuilder requestHandler(RequestHandler requestHandler) {
            this.requestHandler = requestHandler;
            return this;
        }

        public ApiRouteBuilder method(String method) {
            this.method = method;
            return this;
        }

        public ApiRouteBuilder requestMiddleware(HttpInterceptor requestMiddleware) {
            this.requestMiddleware = requestMiddleware;
            return this;
        }

        public ApiRoute build() {
            return new ApiRoute(this);
        }
    }

    @Data
    public static class ApiRoute implements Serializable {
        private String path;
        private RequestHandler requestHandler;
        private HttpInterceptor requestMiddleware;
        private String method;

        public ApiRoute() {
        }

        public ApiRoute(ApiRouteBuilder builder) {
            this.path = builder.path;
            this.requestHandler = builder.requestHandler;
            this.requestMiddleware = builder.requestMiddleware;
            this.method = builder.method;
        }
    }
}
